#include "QMuscleWindow.h"

void QMuscleWindow::setDefaults(void)
{
    selNode = -1;
    selMuscle = -1;
    moveNode = -1;
    moveMode = false;
    wasFixed = false;

    gridStep = 20;
    hasBinding = false;

    leftButtonPressed = false;

    timer = new QTimer;
    timer->setInterval(10);
    connect(timer, SIGNAL(timeout()), this, SLOT(calc()));

    this->createActions();
    this->createMenus();
    this->createStatusBar();
    this->buildPropertyWidget();
    this->fillPropertyWidget();
    this->stop();

    this->setMode0();
}

void QMuscleWindow::paintEvent(QPaintEvent * /*event*/ )
{
    QPainter painter(this);
    QPen pen;

    painter.setPen(QColor(220,220,220));
    painter.setBrush(QColor(247,247,247));
    painter.drawRect(0,20,centralWidget->width()-1,centralWidget->height()-1);

    painter.setPen(QColor(219,219,219));
    for(int i=0; i<=floor((centralWidget->width()-1)/gridStep); ++i)
    {
        painter.drawLine(gridStep*i, 0, gridStep*i, centralWidget->height()+19);
    }
    for(int i=0; i<=floor((centralWidget->height()-1)/gridStep); ++i)
    {
        painter.drawLine(0, 19+gridStep*i, centralWidget->width()-1, 19+gridStep*i);
    }

    painter.setRenderHint(QPainter::Antialiasing, true);

    pen = QPen(QBrush(Qt::darkGreen), 1);

    for (int i=0; i<connectionList.length(); ++i)
    {
        QPainterPath path;
        path.moveTo(connectionList[i].sender->getPos());
        path.cubicTo(connectionList[i].sender->getPos()+QPointF(0,50),connectionList[i].receiver->getCenterPos()+QPointF(50,0),connectionList[i].receiver->getCenterPos());
        painter.strokePath(path, pen);
    }

    pen = QPen(QBrush(Qt::black), 1);
    painter.setPen(pen);
    for (int i=0; i<mList.length(); ++i)
    {
        if (selMuscle == i)
        {
            pen = QPen(QBrush(Qt::red), 1);
            painter.setPen(pen);
        }
        else if(mList[i]->getType()==1)
        {
            pen = QPen(QBrush(Qt::darkRed), 1);
            painter.setPen(pen);
        }
        else if(mList[i]->getType()==2)
        {
            pen = QPen(QBrush(Qt::darkBlue), 1);
            painter.setPen(pen);
        }

        painter.drawLine(mList[i]->getNodeList()[0]->getPos(),mList[i]->getNodeList()[1]->getPos());

        painter.setBrush(QColor(Qt::lightGray));

        painter.drawEllipse(mList[i]->getCenterPos().x()-2.5, mList[i]->getCenterPos().y()-2.5, 5, 5);

        pen = QPen(QBrush(Qt::black), 1);
        painter.setPen(pen);
    }

    pen = QPen(QBrush(Qt::black), 1);
    painter.setPen(pen);
    painter.setBrush(QColor(Qt::white));

    for (int i=0; i<nList.length(); ++i)
    {
        if (selNode == i)
        {
            pen = QPen(QBrush(Qt::red), 1);
            painter.setPen(pen);
        }
        else
        {
            pen = QPen(QBrush(Qt::black), 1);
            painter.setPen(pen);
        }
        painter.drawEllipse(nList[i]->getPos().x()-5,nList[i]->getPos().y()-5,10,10);
    }

    switch (mode)
    {
    case 0:
        break;
    case 1:
        break;
    case 2:
        if (moveMode) painter.drawLine(nList[moveNode]->getPos(),tempPos);
        break;
    case 3:
        if (moveMode) painter.drawLine(nList[moveNode]->getPos(),tempPos);
        break;
    }
}
void QMuscleWindow::mousePressEvent(QMouseEvent *event)
{
    QPointF bindingPos = QPointF(0,0);
    if(hasBinding) bindingPos = QPoint(gridStep*int(event->posF().x()/gridStep+0.5), 19+gridStep*int((event->posF().y()-19)/gridStep+0.5));
    else bindingPos = event->posF();

    if(event->button()&Qt::LeftButton)
    {
        leftButtonPressed = true;
        switch (mode)
        {
        case 0:
            this->catchNode(event->posF());
            if ((moveNode+1)>0)
            {
                this->selectNode(moveNode);
                propertyWidget->selectNode(moveNode);
                wasFixed = nList[moveNode]->isFixed();
            }
            break;
        case 1:
            this->addNode(bindingPos);
            break;
        case 2:
            this->catchNode(event->posF());
            if (moveMode) tempPos = bindingPos;
            break;
        case 3:
            this->catchNode(event->posF());
            if (moveMode) tempPos = bindingPos;
            break;
        }
    }
    else if(event->button()&Qt::RightButton)
    {
        switch (mode)
        {
        case 0:
            this->catchNode(event->posF());
            if ((moveNode+1)>0)
            {
                if(!leftButtonPressed)
                {
                    nList[moveNode]->setFixed(!nList[moveNode]->isFixed());
                    moveMode = false;
                }
                else
                {
                    wasFixed = !wasFixed;
                }
            }
            break;
       /*case 1:
            break;
       case 2:
            break;
       case 3:
            break;*/

        }
    }

    this->update();
}
void QMuscleWindow::mouseDoubleClickEvent(QMouseEvent *event)
{
    switch (mode)
    {
    case 0:
        this->catchNode(event->posF());
        if ((moveNode+1)>0)
        {
            this->selectNode(moveNode);
            propertyWidget->selectNode(moveNode);
            this->editNetwork(moveNode);
        }
        break;
    case 1:
        break;
    case 2:
        break;
    case 3:
        break;
    }
}
void QMuscleWindow::mouseMoveEvent(QMouseEvent *event)
{
    QPointF bindingPos = QPointF(0,0);
    if(hasBinding) bindingPos = QPoint(gridStep*int(event->posF().x()/gridStep+0.5), 19+gridStep*int((event->posF().y()-19)/gridStep+0.5));
    else bindingPos = event->posF();

    if (moveMode)
    {
        switch (mode)
        {
        case 0:
            if ((event->posF().x()>5)&&(event->posF().x()<centralWidget->width()-5)&&
                    (event->posF().y()>27)&&(event->posF().y()<centralWidget->height()+15))
            {
                nList[moveNode]->setPos(bindingPos);
                for (int i=0; i<mList.length(); ++i)
                {
                    mList[i]->calculateCenterPos();
                }
            }
            nList[moveNode]->setFixed(true);
            break;
        case 1:
            break;
        case 2:
            tempPos = event->posF();
            break;
        case 3:
            tempPos = event->posF();
            break;
        }
    }
    this->update();
}
void QMuscleWindow::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button()&Qt::LeftButton)
    {
        leftButtonPressed = false;
        if (moveMode)
        {
            int sNode;
            switch (mode)
            {
            case 0:
                nList[moveNode]->setFixed(wasFixed);
                break;
            case 1:
                break;
            case 2:
                sNode = moveNode;
                this->catchNode(event->posF());
                if (moveMode)
                {
                    this->addMuscle(nList[sNode], nList[moveNode]);
                }
                break;
            case 3:
                sNode = moveNode;
                this->catchNode(event->posF());
                if (moveMode)
                {
                    this->addMuscle(nList[sNode], nList[moveNode]);
                }
                break;
            }
        }

        moveMode = false;
    }

    this->update();
}
void QMuscleWindow::resizeEvent (QResizeEvent * /*event*/ )
{
    this->setAllowedSize();
}
void QMuscleWindow::closeEvent (QCloseEvent * event)
{
    emit closeSignal();
    event->accept();
}

void QMuscleWindow::addNode(QPointF pos)
{
    QNode *node = new QNode;
    node->setAllowedSize(centralWidget->width(), 22+centralWidget->height());
    node->setPos(pos);
    node->setID(nList.length());
    nList << node;

    connect(nList.last(), SIGNAL(nerveListChanged(int)), this, SLOT(removeConnectionsByNodeID(int)));
    propertyWidget->addItem(node);
}
void QMuscleWindow::addMuscle(QNode* node_1, QNode* node_2)
{
    if (node_1 != node_2)
    {
        QAbstractMuscle *muscle;

        switch(mode)
        {
        case 2:
            muscle = new QSpongeMuscle;
            break;
        case 3:
            muscle = new QPotentialMuscle;
            break;
        }

        muscle->setID(mList.length());
        muscle->addNode(node_1);
        muscle->addNode(node_2);
        muscle->setDefL(sqrt(pow(node_1->getPos().x()-node_2->getPos().x(),2)+pow(node_1->getPos().y()-node_2->getPos().y(),2)));
        mList << muscle;

        propertyWidget->addItem(muscle);
    }
}

void QMuscleWindow::catchNode(QPointF pos)
{
    moveMode = false;
    moveNode = -1;
    for (int i=0; i<nList.length(); ++i)
    {
        if (sqrt(pow(pos.x()-nList[i]->getPos().x(),2)+pow(pos.y()-nList[i]->getPos().y(),2))<10) moveNode = i;
    }
    if ((moveNode+1)>0)
    {
        moveMode = true;
    }
}

void QMuscleWindow::createActions(void)
{
    newAction = new QAction(tr("New"), this);
    newAction->setShortcuts(QKeySequence::New);
    connect(newAction, SIGNAL(triggered()), this, SLOT(reset()));

    saveAction = new QAction(tr("Save"), this);
    saveAction->setShortcuts(QKeySequence::Save);
    connect(saveAction, SIGNAL(triggered()), this, SLOT(save()));

    loadAction = new QAction(tr("Load"), this);
    loadAction->setShortcuts(QKeySequence::Open);
    connect(loadAction, SIGNAL(triggered()), this, SLOT(load()));

    startAction = new QAction(tr("Start"), this);
    startAction->setShortcut(tr("Ctrl+W"));
    connect(startAction, SIGNAL(triggered()), this, SLOT(start()));

    stopAction = new QAction(tr("Stop"), this);
    stopAction->setShortcut(tr("Ctrl+E"));
    connect(stopAction, SIGNAL(triggered()), this, SLOT(stop()));

    exitAction = new QAction(tr("Exit"), this);
    exitAction->setShortcut(tr("Ctrl+Q"));
    connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));

    freeAction = new QAction(tr("Free"), this);
    freeAction->setCheckable(true);
    connect(freeAction, SIGNAL(triggered()), this, SLOT(setMode0()));
    freeAction->setShortcut(tr("Alt+F"));

    nodeAction = new QAction(tr("Node"), this);
    nodeAction->setCheckable(true);
    connect(nodeAction, SIGNAL(triggered()), this, SLOT(setMode1()));
    nodeAction->setShortcut(tr("Alt+N"));

    spongeMuscleAction = new QAction(tr("Sponge Muscle"), this);
    spongeMuscleAction->setCheckable(true);
    connect(spongeMuscleAction, SIGNAL(triggered()), this, SLOT(setMode2()));
    spongeMuscleAction->setShortcut(tr("Alt+S"));

    potentialMuscleAction = new QAction(tr("Potential Muscle"), this);
    potentialMuscleAction->setCheckable(true);
    connect(potentialMuscleAction, SIGNAL(triggered()), this, SLOT(setMode3()));
    potentialMuscleAction->setShortcut(tr("Alt+P"));

    helpAction = new QAction(tr("Help"), this);
    connect(helpAction, SIGNAL(triggered()), this, SLOT(help()));

    aboutAction = new QAction(tr("About"), this);
    connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));

    aboutQtAction = new QAction(tr("About Qt"), this);
    connect(aboutQtAction, SIGNAL(triggered()), this, SLOT(aboutQt()));
}
void QMuscleWindow::createMenus(void)
{
    fileMenu = menuBar()->addMenu(tr("File"));
    fileMenu->addAction(newAction);
    fileMenu->addAction(saveAction);
    fileMenu->addAction(loadAction);
    fileMenu->addSeparator();
    fileMenu->addAction(startAction);
    fileMenu->addAction(stopAction);
    fileMenu->addSeparator();
    fileMenu->addAction(exitAction);

    modeMenu  = menuBar()->addMenu(tr("Mode"));
    modeMenu->addAction(freeAction);
    modeMenu->addAction(nodeAction);
    modeMenu->addAction(spongeMuscleAction);
    modeMenu->addAction(potentialMuscleAction);

    viewMenu  = menuBar()->addMenu(tr("View"));

    aboutMenu = menuBar()->addMenu(tr("About"));
    aboutMenu->addAction(helpAction);
    aboutMenu->addAction(aboutAction);
    aboutMenu->addAction(aboutQtAction);
}
void QMuscleWindow::createStatusBar(void)
{
    statusLabel = new QLabel;
    this->statusBar()->addWidget(statusLabel);
    this->statusBar()->setAutoFillBackground(true);
}

void QMuscleWindow::buildPropertyWidget(void)
{
    propertyWidget = new QPropertyWidget;
    propertyWidget->setFixedWidth(200);
    connect(propertyWidget, SIGNAL(addConnectionSignal(int)), this, SLOT(addConnection(int)));
    connect(propertyWidget, SIGNAL(removeConnectionSignal(int,int,int)), this, SLOT(removeConnection(int,int,int)));
    connect(propertyWidget, SIGNAL(editNetworkSignal(int)), this, SLOT(editNetwork(int)));
    connect(propertyWidget, SIGNAL(removeNodeSignal(int)), this, SLOT(removeNode(int)));
    connect(propertyWidget, SIGNAL(removeMuscleSignal(int)), this, SLOT(removeMuscle(int)));
    connect(propertyWidget, SIGNAL(nodeSelected(int)), this, SLOT(selectNode(int)));
    connect(propertyWidget, SIGNAL(muscleSelected(int)), this, SLOT(selectMuscle(int)));
    connect(propertyWidget, SIGNAL(gridStepChanged(int)), this, SLOT(setGridStep(int)));
    connect(propertyWidget, SIGNAL(bindingChanged(bool)), this, SLOT(setBinding(bool)));

    QDockWidget *dock = new QDockWidget(tr("Properties"), this);
    viewMenu->addAction(dock->toggleViewAction());
    dock->setAllowedAreas(Qt::RightDockWidgetArea);
    dock->setWidget(propertyWidget);
    this->addDockWidget(Qt::RightDockWidgetArea, dock);
}
void QMuscleWindow::fillPropertyWidget(void)
{
    for (int i=0; i<nList.length(); ++i)
    {
        nList[i]->setID(i);
        propertyWidget->addItem(nList[i]);
    }
    for (int i=0; i<mList.length(); ++i)
    {
        mList[i]->setID(i);
        propertyWidget->addItem(mList[i]);
    }
    for (int i=0; i<connectionList.length(); ++i)
    {
        propertyWidget->addConnection(connectionList[i].sender->getID(), connectionList[i].senderChannel, connectionList[i].receiver->getID());
    }
}

QDomElement QMuscleWindow::xmlAddNode(QDomDocument* xmlFile, QNode *node)
{
    QDomElement nodeElement = xmlFile->createElement("NODE");
    nodeElement.setAttribute("id", node->getID());
    nodeElement.setAttribute("is-fixed", node->isFixed());
    nodeElement.setAttribute("pos-x", node->getPos().x());
    nodeElement.setAttribute("pos-y", node->getPos().y());
    nodeElement.setAttribute("vel-x", node->getPosDot().x());
    nodeElement.setAttribute("vel-y", node->getPosDot().y());
    for (int i=0; i<node->getNerveList().length(); ++i)
    {
        nodeElement.appendChild(QNeuronWindow::xmlAddNerve(xmlFile, node->getNerveList()[i]));
    }

    return nodeElement;
}
QDomElement QMuscleWindow::xmlAddConnection(QDomDocument* xmlFile, CONNECTION connection)
{
    QDomElement connectionElement = xmlFile->createElement("CONNECTION");
    connectionElement.setAttribute("sender-id", connection.sender->getID());
    connectionElement.setAttribute("sender-channel", connection.senderChannel);
    connectionElement.setAttribute("receiver-id", connection.receiver->getID());

    return connectionElement;
}
QDomElement QMuscleWindow::xmlAddMuscle(QDomDocument* xmlFile, QAbstractMuscle* muscle)
{
    QDomElement muscleElement = xmlFile->createElement("MUSCLE");
    muscleElement.setAttribute("id", muscle->getID());
    muscleElement.setAttribute("type", muscle->getType());
    muscleElement.setAttribute("node1-id", muscle->getNodeList()[0]->getID());
    muscleElement.setAttribute("node2-id", muscle->getNodeList()[1]->getID());
    muscleElement.setAttribute("def-l", muscle->getDefL());
    muscleElement.setAttribute("k", muscle->getK());
    return muscleElement;
}

QMuscleWindow::QMuscleWindow(void)
{
    centralWidget = new QWidget(this);
    centralWidget->setMinimumSize(400, 400);
    this->setCentralWidget(centralWidget);

    this->setDefaults();
}

void QMuscleWindow::setAllowedSize(void)
{
    for (int i=0; i<nList.length(); ++i)
    {
        nList[i]->setAllowedSize(centralWidget->width(), 22+centralWidget->height());
    }
}

void QMuscleWindow::calc(void)
{
    for (int i=0; i<connectionList.length(); ++i)
    {
        connectionList[i].receiver->addMemPot(connectionList[i].sender->getMemPot(connectionList[i].senderChannel));
    }
    for (int i=0; i<nList.length(); ++i)
    {
        nList[i]->rotate();
        nList[i]->calcMemPot();
    }
    for (int i=0; i<mList.length(); ++i)
    {
        mList[i]->calculateCenterPos();
        if(mList[i]->getType()==2)
        {            
            mList[i]->rotMemPot();
        }
        mList[i]->sendForce();
    }
    this->update();
}

void QMuscleWindow::addConnection(int node)
{
    bool state = timer->isActive();
    if(state) this->stop();

    QStringList items;
    int senderChannel = -1;
    int receiverID = -1;
    bool ok = false;

    for (int i=0; i<nList[node]->getSenderList().length(); ++i)
    {
        items << QString().setNum(nList[node]->getSenderList()[i]);
    }

    QString item = QInputDialog::getItem(this, tr("Set sender nerve ID"), tr("Sender ID:"), items, 0, false, &ok);

    if (ok && !item.isEmpty())
    {
        senderChannel = item.toInt();
        items.clear();

        for (int i=0; i<mList.length(); ++i)
        {
            if(mList[i]->getType()==2) items << QString().setNum(i);
        }

        ok = false;

        item = QInputDialog::getItem(this, tr("Set receiver muscle ID"), tr("Receiver ID:"), items, 0, false, &ok);

        if (ok && !item.isEmpty()) receiverID = item.toInt();

        if ((senderChannel>-1)&&(receiverID>-1))
        {
            CONNECTION conn;
            conn.sender = nList[node];
            conn.senderChannel = senderChannel;
            conn.receiver = mList[receiverID];

            connectionList << conn;

            propertyWidget->addConnection(node, senderChannel, receiverID);
        }
    }

    if(state) this->start();
}
void QMuscleWindow::removeConnection(int sender, int senderChannel, int receiver)
{
    for (int i=0; i<connectionList.length(); ++i)
    {
        if ((connectionList[i].sender->getID() == sender)&&(connectionList[i].senderChannel == senderChannel)&&(connectionList[i].receiver->getID() == receiver))
        {
            connectionList.removeAt(i);
        }
    }

    propertyWidget->removeConnection(sender, senderChannel, receiver);
    this->update();
}
void QMuscleWindow::removeConnectionsByNodeID(int id)
{
    for (int i=connectionList.length()-1; i>=0; --i)
    {
        if (connectionList[i].sender->getID() == id)
        {
            propertyWidget->removeConnection(connectionList[i].sender->getID(), connectionList[i].senderChannel, connectionList[i].receiver->getID());
            connectionList.removeAt(i);
        }
    }
}
void QMuscleWindow::editNetwork(int node)
{
    QNeuronWindow *neuronWindow = new QNeuronWindow;
    connect(timer, SIGNAL(timeout()), neuronWindow, SLOT(emitImpulse()));
    connect(this, SIGNAL(resetSignal()), neuronWindow, SLOT(close()));
    connect(this, SIGNAL(closeSignal()), neuronWindow, SLOT(close()));

    neuronWindow->setNerveList(nList[node]->getNerveList());
    connect(neuronWindow, SIGNAL(nerveListChanged(QList<QNerveTissue*>)), nList[node], SLOT(setNerveList(QList<QNerveTissue*>)));
    neuronWindow->show();
}

void QMuscleWindow::removeMuscle(int muscle)
{
    bool state = timer->isActive();
    if(state) this->stop();

    for (int i=connectionList.length()-1; i>=0; --i)
    {
        if (connectionList[i].receiver->getID() == muscle)
        {
            this->removeConnection(connectionList[i].sender->getID(), connectionList[i].senderChannel, connectionList[i].receiver->getID());
        }
    }

    mList.removeAt(muscle);

    for (int i=0; i<mList.length(); ++i)
    {
        mList[i]->setID(i);
    }
    propertyWidget->removeMuscle(muscle);

    if(state) this->start();

    this->update();
}
void QMuscleWindow::removeNode(int node)
{
    bool state = timer->isActive();
    if(state) this->stop();

    for (int i=mList.length()-1; i>=0; --i)
    {
        if ((mList[i]->getNodeList()[0]->getID() == node)||(mList[i]->getNodeList()[1]->getID() == node))
        {
            this->removeMuscle(i);
        }
    }

    for (int i=connectionList.length()-1; i>=0; --i)
    {
        if (connectionList[i].sender->getID() == node)
        {
            this->removeConnection(connectionList[i].sender->getID(), connectionList[i].senderChannel, connectionList[i].receiver->getID());
        }
    }

    nList.removeAt(node);

    propertyWidget->removeNode(node);

    for (int i=0; i<nList.length(); ++i)
    {
        nList[i]->setID(i);
    }

    if(state) this->start();

    this->update();
}

void QMuscleWindow::selectNode(int node)
{
    selNode = node;
    if (selMuscle>=0) selMuscle = -1;
    this->update();
}
void QMuscleWindow::selectMuscle(int muscle)
{
    if (selNode>=0) selNode = -1;
    selMuscle = muscle;
    this->update();
}

void QMuscleWindow::setGridStep(int _gridStep)
{
    gridStep = _gridStep;
    this->update();
}
void QMuscleWindow::setBinding(bool _hasBinding)
{
    hasBinding = _hasBinding;
}

void QMuscleWindow::reset(void)
{
    if (timer->isActive()) this->stop();

    for (int i=nList.length()-1; i>=0; --i) propertyWidget->removeNode(i);
    for (int i=mList.length()-1; i>=0; --i) propertyWidget->removeMuscle(i);
    for (int i=connectionList.length()-1; i>=0; --i) propertyWidget->removeConnection(connectionList[i].sender->getID(), connectionList[i].senderChannel, connectionList[i].receiver->getID());

    nList.clear();
    mList.clear();
    connectionList.clear();

    this->update();

    emit resetSignal();
}
void QMuscleWindow::save(void)
{
    bool state = timer->isActive();
    if (state) this->stop();

    QString fileName = QFileDialog::getSaveFileName(this, tr("Save Model") , "", "*.xml");

    if (!fileName.isEmpty())
    {
        QFile *file = new QFile(fileName);
        file->open(QIODevice::WriteOnly);
        QTextStream out(file);

        QDomDocument *xmlFile = new QDomDocument;
        QDomElement rootElement = xmlFile->createElement("ModelData");
        xmlFile->appendChild(rootElement);
        QDomElement nodesElement = xmlFile->createElement("Nodes");
        rootElement.appendChild(nodesElement);

        for (int i=0; i<nList.length(); ++i)
        {
            nodesElement.appendChild(this->xmlAddNode(xmlFile, nList[i]));
        }

        QDomElement musclesElement = xmlFile->createElement("Muscles");
        rootElement.appendChild(musclesElement);

        for (int i=0; i<mList.length(); ++i)
        {
            musclesElement.appendChild(this->xmlAddMuscle(xmlFile, mList[i]));
        }

        QDomElement connectionsElement = xmlFile->createElement("Connections");
        rootElement.appendChild(connectionsElement);

        for (int i=0; i<connectionList.length(); ++i)
        {
            connectionsElement.appendChild(this->xmlAddConnection(xmlFile, connectionList[i]));
        }

        out.setCodec("UTF-8");
        xmlFile->save(out, 4, QDomNode::EncodingFromTextStream);
        file->close();

        this->update();
    }

    if (state) this->start();
}
void QMuscleWindow::load(void)
{
    if (timer->isActive()) this->stop();

    QString fileName = QFileDialog::getOpenFileName(this, tr("Open Model"), "", "*.xml");
    if (!fileName.isEmpty())
    {
        this->reset();
        QFile file(fileName);
        QXmlInputSource xmlInputSource(&file);
        QXmlModelHandler xmlModelHandler;
        QXmlSimpleReader xmlSimpleReader;
        xmlSimpleReader.setContentHandler(&xmlModelHandler);
        xmlSimpleReader.parse(xmlInputSource);
        file.close();

        nList = xmlModelHandler.getNList();
        for (int i=0; i<nList.length(); ++i)
        {
            nList[i]->setAllowedSize(centralWidget->width(), 20+centralWidget->height());
            connect(nList[i], SIGNAL(nerveListChanged(int)), this, SLOT(removeConnectionsByNodeID(int)));
        }
        mList = xmlModelHandler.getMList();
        connectionList = xmlModelHandler.getConnectionList();

        this->fillPropertyWidget();

        this->resize(xmlModelHandler.getXSize(), xmlModelHandler.getYSize());
        this->update();
    }
}
void QMuscleWindow::start(void)
{
    timer->start();
    startAction->setDisabled(true);
    stopAction->setDisabled(false);
    statusLabel->setText(tr("Running... "));
}
void QMuscleWindow::stop(void)
{
    timer->stop();
    stopAction->setDisabled(true);
    startAction->setDisabled(false);
    statusLabel->setText(tr("Stoped... "));
}
void QMuscleWindow::exit(void)
{
    this->close();
}

void QMuscleWindow::setMode0(void)
{
    mode = 0;
    this->setWindowTitle(tr("Muscle Model - Free Mode"));

    if (!freeAction->isChecked()) freeAction->setChecked(true);
    if (nodeAction->isChecked()) nodeAction->setChecked(false);
    if (spongeMuscleAction->isChecked()) spongeMuscleAction->setChecked(false);
    if (potentialMuscleAction->isChecked()) potentialMuscleAction->setChecked(false);
}
void QMuscleWindow::setMode1(void)
{
    this->setWindowTitle(tr("Muscle Model - Node Mode"));
    mode = 1;

    if (freeAction->isChecked()) freeAction->setChecked(false);
    if (!nodeAction->isChecked()) nodeAction->setChecked(true);
    if (spongeMuscleAction->isChecked()) spongeMuscleAction->setChecked(false);
    if (potentialMuscleAction->isChecked()) potentialMuscleAction->setChecked(false);
}
void QMuscleWindow::setMode2(void)
{
    this->setWindowTitle(tr("Muscle Model - Sponge Muscle Mode"));
    mode = 2;

    if (freeAction->isChecked()) freeAction->setChecked(false);
    if (nodeAction->isChecked()) nodeAction->setChecked(false);
    if (!spongeMuscleAction->isChecked()) spongeMuscleAction->setChecked(true);
    if (potentialMuscleAction->isChecked()) potentialMuscleAction->setChecked(false);
}
void QMuscleWindow::setMode3(void)
{
    this->setWindowTitle(tr("Muscle Model - Potential Muscle Mode"));
    mode = 3;

    if (freeAction->isChecked()) freeAction->setChecked(false);
    if (nodeAction->isChecked()) nodeAction->setChecked(false);
    if (spongeMuscleAction->isChecked()) spongeMuscleAction->setChecked(false);
    if (!potentialMuscleAction->isChecked()) potentialMuscleAction->setChecked(true);
}

void QMuscleWindow::help(void)
{
    QMessageBox::question(this, tr("Help"), "Quick help text");
}
void QMuscleWindow::about(void)
{
    QMessageBox::information(this,"About","Model v<b>DATE</b>");
}
void QMuscleWindow::aboutQt(void)
{
    QMessageBox::aboutQt(this);
}
